local Obj         = require("core.Obj")
local UtilityExcel      = require("excel.Skill").Utility
local SkillExcel        = require("excel.Skill").Skill
local SkillDefine       = require("skill.Define")
local Skill         = require("skill.Skill")
local Unit          = require("skill.Unit")
local Conditions      = require("skill.Conditions")
local MultiTarget     = require("skill.MultiTarget")
local Notify          = require("skill.Notify")
local MapGrid = require("core.MapGrid")

local UTILITY_TYPE_MIAN   = SkillDefine.UTILITY_TYPE_MIAN
local UTILITY_TYPE_MUST   = SkillDefine.UTILITY_TYPE_MUST
local AOE_TYPE_SINGLE   = SkillDefine.AOE_TYPE_SINGLE

local MAX_POOL_NUM = 30000

if not pool then
    pool = {}
    for k=1, MAX_POOL_NUM do
        pool[k] = {}
    end
end

function getInstance()
    local node = pool[#pool]
    if node then
        pool[#pool] = nil
        node.onEnd  = onEnd
        node.onStart= onStart
        return node
    end
    node = {}
    node.onEnd  = onEnd
    node.onStart= onStart
    return node
end

-- 销毁
function destroy(node)
    if #pool < MAX_POOL_NUM then
        pool[#pool+1] = node
    end
end


--*************** Node 主技能节点 ****************

-- 发动
function onStart(node)
    node.run = false

    Skill.timer:insert(SkillExcel[node.skillID].actionDelay, node)
end

local argsTemp={}
-- 到达
function onEnd(node)
    if node.run then -- 上次报错过
        return
    end
    destroy(node)
    node.run      = true

    local obj     = Obj.getObj(node.id, node.uid)
    if not obj then
        return
    end

    if obj.obj_type == Obj.TYPE_SKILL then  --场景技能重设插入的格子(因为场景技能对象无视任何场景)
        local partition = Obj.scenes_9grid[obj.scene_id]
        if partition then
            MapGrid.remove(partition, obj)
            MapGrid.insert(partition, obj)
        end
    end

    local skillConfig = SkillExcel[node.skillID]
    local target    = Obj.getObj(node.tid, node.tuid)
    local level     = node.level

    -- 生成作用
    local len = #utilitysStrs
    local utilityIndex=0
    while utilityIndex< len do
        utilityIndex = utilityIndex+1
        local value       = utilitysStrs[utilityIndex]
        local utilityID     = skillConfig[value[1]]
        local utilityArgsLevel  = skillConfig[value[2]]
        local delay       = skillConfig[value[3]]
        local utilityConfig   = UtilityExcel[utilityID]
        node.utilityIndex   = utilityIndex
        node.utilityID      = utilityID
        node.utilityConfig    = utilityConfig
        node.utilityArgs    = utilityArgsLevel[level] or utilityArgsLevel[#utilityArgsLevel] or argsTemp
        node.delay        = delay * skillConfig.timescale

        local result = addUnit(obj, target, node, utilityIndex==UTILITY_TYPE_MIAN ) -- 主作用
        if not result and utilityIndex < UTILITY_TYPE_MUST then -- 非必定作用添加失败 停止附加作用
            utilityIndex = 4
        end
    end
end

local multiHandles = MultiTarget.multiHandles
-- 生成作用单元
function addUnit(obj, target, node, isMain)
    local utilityConfig = node.utilityConfig
    if not utilityConfig then return end
    -- 判断前提条件是否成立
    if Conditions.prerequisites(obj, target, node, utilityConfig) then

        if isMain and utilityConfig.enableID[1]~=0 then
            Notify.GC_SKILL_EFFECT(obj, node.sceneID, utilityConfig, node.x, node.y)
        end

        local multiHandle = multiHandles[utilityConfig.multiTarget]
        if multiHandle then -- 多目标
            local tx, ty = node.tx, node.ty

            multiHandle(obj, target, node)  -- MultiTarget 产生多个目标
            node.tx, node.ty = tx, ty
        else      -- 单目标
            local unit      = Unit.clone(node)
            unit.delay      = Unit.calcFlyTime(unit)  -- 飞行时间 + 作用延迟时间
            unit.delayFlyTime = node.delay
            unit:onStart()
        end
        return true
    end

    return utilityConfig.aoeType ~= AOE_TYPE_SINGLE --非单体 继续触发其他作用
end

utilitysStrs = utilitysStrs or {
    {"mainUtility",   "mainUtilityArgs",    "mainDelay"},   --主作用
    {"appendUtility1",  "appendUtilityArgs1", "appendDelay1"},  --副作用1
    {"appendUtility2",  "appendUtilityArgs2", "appendDelay2"},  --副作用2
    {"appendUtility3",  "appendUtilityArgs3", "appendDelay3"},  --副作用3
    {"mustUtility",   "mustUtilityArgs",    "mustDelay"},   --必定作用
}
